using UnityEngine;
using System.Collections;
using System.Reflection;
//
//ON_BARREL_FIRE
//ON_LAND
//ON_RUN
//ON_MELEE
//ON_SPUDGUN_PROJECTILE_LANDING
//ON_LOOT_ENTITY
//ON_COLLIDE_BUSH
//ON_USED_TAPE
//ON_ENTERED_BUILDSCREEN
//ON_JUMP
//ON_OVERENCUMBERED
//ON_CLICKED_STARTMENU
//ON_STUNNED
//ON_WON_GAME
//ON_LOST_GAME
//ON_NIGHTTIME
//ON_DAYTIME
//ON_FIGHT


//Måste komma på ett sätt att få ljuden att vara mono för den egna spelaren men positional för övriga spelare.
//Ett sätt att fadea ljud in och ut.
//



public class SoundSystem : MonoBehaviour {
	public AudioClip damaged;
//	public AudioClip stunned;
//	public AudioClip overEncumbered;

	public AudioClip meleeSound;
	public AudioClip gunShot;
	public AudioClip spudgunShot;
	public AudioClip spudgunExplosion;
	
	public AudioClip drinkingSound;
	public AudioClip lootSound;

	//public AudioClip bushRustle;

	public AudioClip buildScreenSound;
	public AudioClip menuClick;

	public AudioClip winstMusic;
	public AudioClip lostMusic;
	
	public AudioClip[] fightMusic;
	public AudioClip[] dayMusic;
	public AudioClip[] nightMusic;
	
	public AudioClip[] jumps;
	public AudioClip[] landings;
	public AudioClip[] footsteps;
	public AudioClip[] tapes;


	//footstepSpeed is the var that differs depending on how fast the character is;
	public float footstepSpeed = 0.4f;
	//higher musictimermax gives a low probability of music playing often.
	public float musicTimerMax = 1f;
	
	public int ifPlay;
	public float musicFadeLength = 3;
	public float musicVolume = 0.1f;
	
	public float tempTimer = 10f;
	public bool night = false;
	public bool fight= false;
	
	public float fightLength = 1f;
	private float fightElapsed = 0f;
	private float fightStart = 0f;
	
	private bool landed;
	private bool newStep = true;
	private int currentFootstep = 0;
	private float footstepTimer = 0f;
	
	private bool playMusic;
	private bool isNowPlaying = false;
	private bool playFightMusic = false;
	private int ifPlayMax = 0;//3;	
	private float musicTimer = 1f;
	private float musicClipLengthPlayed;
	public GameObject myMainMusicManager;
	private float maxMusicVolume = 0.2f;
	private float minMusicVolume = 0.0f;
	private bool firstTimeFighting = true;
	private bool firstTimeDayNight = true;
	private float fadeSpeed = 0.05f;
	private AudioClip clip;
	
	private bool meleeAvalible = true;
	private float meleeTimer = 0f;
	public float meleeDelay = 2f;
	private float meleeStart = 0f;	
	
	
	void Awake(){
		foreach (FieldInfo fi in this.GetType().GetFields()){
			if (fi.FieldType == typeof(AudioClip)){
				if (fi.GetValue(this).ToString() == "null"){
					AudioClip newAudio = new AudioClip();
					fi.SetValue(this,newAudio);
					this.enabled = false;
					Debug.LogWarning("AudioClip " + fi.Name + " in " + this.GetType() + " in gameojbect " + this.name + " is missing. SoundsSystem will be disabled.");
				}
			}
		}		
	}
	
	void Start() {
		
		if(myMainMusicManager == null){
			myMainMusicManager = GameObject.Find ("/Player(Clone)/MyMainMusicManager");
		}
		
		if (myMainMusicManager != null) {
			clip = myMainMusicManager.audio.clip;
		}
		
		Debug.Log("Music Mgr: " + myMainMusicManager);
		
		//On winning game music.
		Listeners.inst ().add (Channel.ON_WON_GAME, delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(winstMusic, transform.position);
//Missing sound
			}
		);
		//On losing game music.
			Listeners.inst ().add (Channel.ON_LOST_GAME,delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(lostMusic, transform.position);
//missing sound
			}
		);
		
				//On winning game music.
		Listeners.inst ().add (Channel.ON_CONSUME_ENTITY, delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(drinkingSound, transform.position);
//Missing sound
			}
		);

		Listeners.inst().add(Channel.ON_FIGHT, delegate(PlayerState state) {
			Debug.Log("Fight "+fight);
			fightStart = Time.time;      
			if(fight != true){
				AudioSource.PlayClipAtPoint(fightMusic[Random.Range(0,fightMusic.Length)],state.transform.position);
				fight = true;
				fightElapsed = 0;
			}
		});

		Listeners.inst().add(Channel.ON_TURNED_NIGHT, delegate(PlayerState state) {
			night = true;
		});
		Listeners.inst().add(Channel.ON_TURNED_DAY, delegate(PlayerState state) {
			night = false;
		});



//On jump sound.
		Listeners.inst ().add (Channel.ON_JUMP, delegate(PlayerState state) {
				Debug.Log ("Jumping!!!! " + /*obj.getPlayer()*/ transform.position);
				AudioSource.PlayClipAtPoint(jumps[Random.Range(0, jumps.Length)], state.transform.position);
				landed = false;
//Missing sound
			}
		);

		// On barrel fire sound.
		Listeners.inst().add(Channel.ON_FIRE, delegate(PlayerState state) {
				if (state.getWeapon().entityType == 4){ //getBarrelPoint().spudGun) {
					AudioSource.PlayClipAtPoint(gunShot, transform.position);
					Debug.LogWarning("checking listeners");
				} else {
					AudioSource.PlayClipAtPoint(spudgunShot, transform.position);
//Missing sound
				}
			}
		);

//On landing sound.
		Listeners.inst().add (Channel.ON_LAND, delegate(PlayerState state){
				AudioSource.PlayClipAtPoint(landings[Random.Range(0, landings.Length)], transform.position);
				landed = true;
			}
		);

		// On run. Footstep sound - When moving and grounded, not when landing.
		Listeners.inst().add (Channel.ON_RUN, delegate(PlayerState state){
				Debug.LogWarning("Running");
				if(footstepTimer <= 0f){
					footstepTimer = footstepSpeed;
					newStep = true;
				}
				else if(!landed){
					footstepTimer = footstepSpeed;
					newStep = false;
				}
				else{
					footstepTimer -= Time.deltaTime;
				}

				if(newStep){
					AudioSource.PlayClipAtPoint(footsteps[currentFootstep], transform.position);
					newStep = false;
					currentFootstep++;
				}
			}
		);

		// On melee sound
		Listeners.inst ().add(Channel.ON_MELEE, delegate(PlayerState state){
				if(meleeAvalible){
					AudioSource.PlayClipAtPoint(meleeSound, transform.position);
					meleeStart = Time.time;
					meleeTimer = 0F;
					meleeAvalible = false;
				}
//Missing sound
			}
		);

		//On spudgun's projectile's landing sound (explosion)
		Listeners.inst ().add (Channel.ON_SPUDGUN_PROJECTILE_LANDING, delegate(PlayerState state){
				AudioSource.PlayClipAtPoint(spudgunExplosion, transform.position);
				//transform.position is wrong??, replace with landing site of projectile.
//Missing sound
			}
		);

		//On loot entity sound.
		Listeners.inst ().add (Channel.ON_LOOT_ENTITY, delegate(PlayerState state){
				Entity weapon = state.getWeapon();

				Debug.Log("Sound for Weapontype: " + weapon);

				if (weapon != null) {

					if (weapon.entityType == 8){
						AudioSource.PlayClipAtPoint(drinkingSound, transform.position);
//Missing sound
					}

					if (weapon.entityType == 9){
						AudioSource.PlayClipAtPoint(tapes[Random.Range(0, tapes.Length)], transform.position);
					}
					else{
						AudioSource.PlayClipAtPoint(lootSound, transform.position);
//Missing sound
					}
				}
			}
		);

//On walking into a bush
//		Listeners.inst ().add (Channel.ON_COLLIDE_BUSH, delegate(PlayerState state){
//				AudioSource.PlayClipAtPoint(bushRustle, transform.position);
////Missing sound
//			}
//		);

		//On using tape in the building menu.
		Listeners.inst ().add(Channel.ON_USED_TAPE, delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(tapes[Random.Range (0, tapes.Length)], transform.position);
			}
		);

		//On entering building screen
		Listeners.inst ().add (Channel.ON_ENTERED_BUILDSCREEN, delegate(PlayerState state) {
			if (buildScreenSound != null) {
				AudioSource.PlayClipAtPoint(buildScreenSound, transform.position);
//Missing sound
			}
		});

		//On Damage sound.
		Listeners.inst ().add (Channel.ON_DAMAGE, delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(damaged, transform.position);
//Missing sound
			}
		);

//		//On Stunned
//		Listeners.inst ().add(Channel.ON_STUNNED, delegate(PlayerState state) {
//				AudioSource.PlayClipAtPoint(stunned, transform.position);
////Missing sound
//			}
//		);

		//On clicked in startmenu.
		Listeners.inst ().add (Channel.ON_CLICKED_STARTMENU, delegate(PlayerState state) {
				AudioSource.PlayClipAtPoint(menuClick, transform.position);
//Missing sound
			}
		);

		//On over encumbered.
//		Listeners.inst ().add (Channel.ON_OVERENCUMBERED, delegate(PlayerState state) {
//				AudioSource.PlayClipAtPoint(overEncumbered, transform.position);
////Missing sound
//			}
//		);
	}
	void Update(){
		meleeTimer+=Time.deltaTime;
		if(!meleeAvalible){
			meleeTimer += Time.deltaTime;
			if(meleeTimer>meleeStart+meleeDelay){
				meleeAvalible = true;
			}
		}
		if(fight){//if we're fighting
			
			Debug.Log ("fighting");
			fightElapsed += Time.deltaTime;
			if(fightElapsed>fightStart+fightLength){
				fight = false;
			}
		}
		
		if (myMainMusicManager == null) return;
		
		//randomizes how often the music will play.
		if(musicTimer <= 0f && !fight && !playFightMusic){//if musictimer is 0 & we aint fighting and no fightingmusic is playing
			if(ifPlay != 0){//if functionrandomer got the wrong number
				ifPlay = Random.Range (0, ifPlayMax);//functionrandomer may random a number
			}else{//if functionrandomer got the right number
				playMusic = true;//music may play
				ifPlay  = ifPlayMax;//function randomer got a different number
			}
			
			musicTimer = musicTimerMax;//musictimer is reset
		}else if (!fight && !playFightMusic){//if were not fighting and no fightingmusic is playing
			musicTimer -= Time.deltaTime;//count down musictimer
			
		}
		
		
		
		//TEMP!
//		if(tempTimer <= 0f){//if temptimer =0
//			
//			if(fight){//if were fighting
//				fight = false;//we aint fighting
//				tempTimer= 10f;
//			}else{//if were not fighting
//				fight = true;//were fighting
//				tempTimer = 10f;//temptimer is reset
//			}
//		}else{//if temptimer aint 0
//			tempTimer -= Time.deltaTime;//count down temptimer
//		}
		
		//FUCK THIS!
		
		
		
		if(isNowPlaying)//if music is playing
			musicClipLengthPlayed += Time.deltaTime;//count up how long clip has played
		else//if music aint playing
			musicClipLengthPlayed += 0;//music has been played 0sec
			
		//plays the right randomized music depending on situation.
		
		
		
		if(fight){//if we're fighting
			
			Debug.Log ("fighting");
			fightElapsed += Time.deltaTime;
			if(fightElapsed>fightStart+fightLength){
				fight = false;
			}
			
			playMusic = false; //no other may start playing
			Debug.LogWarning("We're fighting");
			
			if(isNowPlaying &&	myMainMusicManager.audio.volume > minMusicVolume && !playFightMusic){//if something is playing thats not fightingmusic and the volume is high
				
				if (myMainMusicManager != null) {
					myMainMusicManager.audio.volume -= (fadeSpeed * Time.deltaTime); //lower the volume
				}
				
				Debug.LogWarning("lowering other songs to play fightmusic");
				
			}else if(myMainMusicManager.audio.volume <= minMusicVolume && !playFightMusic && isNowPlaying){//if the volume is low and fightingmusic aint playing
				
				myMainMusicManager.audio.Stop();//turn of the music
				isNowPlaying = false;//tell function that music aint playing
				Debug.LogWarning("turned Off daynightmusic");
				
			}else if(!playFightMusic && !isNowPlaying){//if no fightingmusic is playing
				if(firstTimeFighting){
					myMainMusicManager.audio.loop = true;//loop the music
					myMainMusicManager.audio.clip = fightMusic[Random.Range(0,fightMusic.Length)];//change the music to fightmusic
					myMainMusicManager.audio.Play();//play the music
					Debug.LogWarning("We're fighting, lets play some " + myMainMusicManager.audio.loop + "ly looping music!");
					musicClipLengthPlayed = 0f; // tell function music has played o sec
					firstTimeFighting = false;
				}else if(myMainMusicManager.audio.volume < maxMusicVolume){
					myMainMusicManager.audio.volume += (fadeSpeed * Time.deltaTime);
				}else{
					playFightMusic = true; //tell function fightingmusic is now playing
					isNowPlaying = true; // tell function music is playing
				}
			}
		}else  if(playFightMusic){//if we're not fighting but fightingmusic is playing
			
			if(myMainMusicManager.audio.volume > minMusicVolume){//if the volume is high
				
				myMainMusicManager.audio.volume -= (fadeSpeed * Time.deltaTime);//lower the volume
				Debug.LogWarning("The fight is over lowering fightmusic");
				
			}else{
				myMainMusicManager.audio.loop = false;//stop looping
				myMainMusicManager.audio.Stop ();//stop the music
				playFightMusic = false;//tell function fightmusic aint playing
				isNowPlaying = false; // tell function music aint playing
				firstTimeFighting = true;
			}
			
			
			
			
		}else if(night){//if its night
			if(playMusic && !isNowPlaying){
				Debug.LogWarning("Its night, lets play some music!");
				myMainMusicManager.audio.clip = nightMusic[Random.Range(0, nightMusic.Length)];//change the current music to night music
				myMainMusicManager.audio.Play();//play music
				playMusic = false;//tell function no other music may play
				isNowPlaying = true;//tell function something is playing
				musicClipLengthPlayed = 0f;//tell function clip has played 0sec
				firstTimeDayNight = false;
			}else if(myMainMusicManager.audio.volume < maxMusicVolume){
				myMainMusicManager.audio.volume += (fadeSpeed * Time.deltaTime);
			}
			
		}else if(!night){//if not night
			Debug.LogWarning("daydaydyaydayydaydyaydyay");
			if(playMusic && !isNowPlaying){
				
				myMainMusicManager.audio.clip = dayMusic[Random.Range(0, dayMusic.Length)];//change current clip to daymusic
				myMainMusicManager.audio.volume = minMusicVolume;
				myMainMusicManager.audio.Play();//play music low once
				playMusic = false;//tell function not to play any other music
				isNowPlaying = true;//tell function something is playing
				musicClipLengthPlayed = 0f;//tell function music has played 0 sec
				firstTimeDayNight = false;
				
				Debug.LogWarning("Its day, lets play some music!");
				
			}
			if(myMainMusicManager.audio.volume < maxMusicVolume){
				
				myMainMusicManager.audio.volume += (fadeSpeed * Time.deltaTime);
				Debug.LogWarning("dayMusic Getting High");
			}
		}
	
		if(!fight && musicClipLengthPlayed >= myMainMusicManager.audio.clip.length){//if were not fighting and the clip has played as long as or longer than the length of the clip
		isNowPlaying = false;//tell function nothing is playing
		}	
	}
}